﻿using System;
using System.Web;
using System.Net;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace cludg.Web.Core.Utils
{
	public static class LoginzaUtils
	{
		public const string LoginzaServer = "http://loginza.ru";
		public const string LoginzaLinkStr = "<script src=\"{0}/js/widget.js\" type=\"text/javascript\"></script>\n" +
				"<a href=\"{0}/api/widget?token_url={2}\" id=\"loginza\">{1}</a>";
		public const string LoginzaInfoUrl = "{0}/api/authinfo?token={1}";

		public static string GenerateLoginLink(string linkText, string callbackUrl)
		{
			return String.Format(LoginzaLinkStr, LoginzaServer, linkText, HttpUtility.UrlEncode(callbackUrl));
		}

		public static string GenerateInfoUrl(string tokenKey)
		{
			return String.Format(LoginzaInfoUrl, LoginzaServer, tokenKey);
		}

		public static LoginzaUserInfo RequestUserInfo(string tokenKey)
		{
			var request = WebRequest.Create(GenerateInfoUrl(tokenKey));
			var response = request.GetResponse();
			JObject rawResult;
			using (var reader = new JsonTextReader(new StreamReader(response.GetResponseStream())))
			{
				rawResult = JObject.Load(reader);
			}

			if (!String.IsNullOrEmpty(rawResult.Value<string>("error_type")))
				throw new LoginzaError(rawResult);

			return new LoginzaUserInfo(rawResult);
		}

		public static bool TryRequestUserInfo(string tokenKey, out LoginzaUserInfo info)
		{
			LoginzaError error;
			return TryRequestUserInfo(tokenKey, out info, out error);
		}

		public static bool TryRequestUserInfo(string tokenKey, out LoginzaUserInfo info, out LoginzaError error)
		{
			info = null;
			error = null;
			try
			{
				info = RequestUserInfo(tokenKey);
				return true;
			}
			catch (LoginzaError e)
			{
				error = e;
				return false;
			}
		}

		public class LoginzaUserInfo
		{
			public string Identity
			{
				get { return Raw.Value<string>("identity"); }
			}

			public string Provider
			{
				get { return Raw.Value<string>("provider"); }
			}

			public string Email
			{
				get { return Raw.Value<string>("email"); }
			}

			public string Photo
			{
				get { return Raw.Value<string>("photo"); }
			}

			public string FirstName
			{
				get
				{
					return (Raw["name"] == null) ? string.Empty : Raw["name"].Value<string>("first_name");
				}
			}

			public string LastName
			{
				get
				{
					return (Raw["name"] == null) ? string.Empty : Raw["name"].Value<string>("last_name");
				}
			}

			public string FullName
			{
				get
				{
					return (Raw["name"] == null) ? string.Empty : Raw["name"].Value<string>("full_name");
				}
			}

			public string Nickname
			{
				get { return Raw.Value<string>("nickname"); }
			}

			public JObject Raw { get; private set; }

			public LoginzaUserInfo(JObject raw)
			{
				Raw = raw;
			}
		}

		public class LoginzaError : ApplicationException
		{
			public JObject Raw { get; private set; }
			public string ErrorType { get; private set; }

			public LoginzaError(JObject raw)
				: base(raw.Value<string>("error_message"))
			{
				Raw = raw;
				ErrorType = raw.Value<string>("error_type");
			}
		}
	}
}